package com.migration.service.impl;

import com.migration.model.newdb.RiskChainConsequence;
import com.migration.model.newdb.RiskChainConsequenceChemical;
import com.migration.model.olddb.RaConsequence;
import com.migration.model.olddb.RaDeviateReason;
import com.migration.model.olddb.RaFaultChainsDetail;
import com.migration.model.olddb.RaFaultChainsMeasure;
import com.migration.model.olddb.RaRiskGrade;
import com.migration.service.RiskChainConsequenceService;
import com.migration.util.CommonUtils;
import com.migration.util.JsonUtils;
import jakarta.persistence.EntityManager;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 事故链-后果表服务实现类
 */
@Slf4j
@Service
public class RiskChainConsequenceServiceImpl implements RiskChainConsequenceService {

    @Override
    public List<RiskChainConsequence> migrateConsequenceData(
            EntityManager oldEntityManager,
            EntityManager newEntityManager,
            Map<Long, RaConsequence> consequenceMap,
            Map<Long, Set<Long>> sourceIdToConsequenceIds,
            List<RaFaultChainsDetail> detailList,
            Map<Long, RaDeviateReason> reasonMap) {

        // 获取风险等级数据
        Map<String, RaRiskGrade> riskGradeMap = getRiskGradeMap(oldEntityManager);

        Set<Long> processedConsequenceIds = new HashSet<>();
        List<RiskChainConsequence> consequenceEntityList = new ArrayList<>();

        // 第一步：预处理数据，收集不同的parent_id和reason_id组合
        Map<String, List<RaFaultChainsDetail>> groupedDetails = new HashMap<>();

        // 按照parent_id和reason_id分组
        for (RaFaultChainsDetail detail : detailList) {
            if (detail.getParentId() != null && detail.getReasonId() != null) {
                String groupKey = detail.getParentId() + "_" + detail.getReasonId();
                if (!groupedDetails.containsKey(groupKey)) {
                    groupedDetails.put(groupKey, new ArrayList<>());
                }
                groupedDetails.get(groupKey).add(detail);
            }
        }

        // 第二步：对每个组内的数据按照parent_path排序，并分配序列号
        Map<Long, Integer> detailIdToSerialNum = new HashMap<>();

        for (List<RaFaultChainsDetail> group : groupedDetails.values()) {
            // 按照parent_path排序
            group.sort(Comparator.comparing(
                    detail -> detail.getParentPath() == null ? "" : detail.getParentPath()
            ));

            // 分配序列号
            for (int i = 0; i < group.size(); i++) {
                detailIdToSerialNum.put(group.get(i).getId(), i + 1); // 序列号从1开始
            }
        }

        for (Long sourceId : sourceIdToConsequenceIds.keySet()) {
            if (consequenceMap.containsKey(sourceId)) {
                RaConsequence consequence = consequenceMap.get(sourceId);

                if (processedConsequenceIds.contains(consequence.getId())) {
                    continue; // 跳过已处理的后果节点
                }

                // 查找该后果节点对应的事故链详情
                for (RaFaultChainsDetail detail : detailList) {
                    if (detail.getConsequenceId() != null && detail.getConsequenceId().equals(consequence.getId())) {
                        RiskChainConsequence consequenceEntity = new RiskChainConsequence();

                        // 设置基础属性
                        consequenceEntity.setId(detail.getId()); // 主键
                        consequenceEntity.setConsequenceId(detail.getId() + "");
                        consequenceEntity.setTenantId(1L);
                        consequenceEntity.setDepartmentId(consequence.getTenantId().longValue()); // 默认部门

                        // 设置分析类型
                        consequenceEntity.setAnalysisType(detail.getFaultChainsType() != null ? detail.getFaultChainsType().intValue() : 1);

                        // 设置原因ID和影响节点ID
                        Long reasonId = detail.getReasonId();
                        Long influenceId = detail.getInfluenceId();

                        if (reasonId != null) {
                            consequenceEntity.setCauseId(reasonId.toString());

                            // 从reasonMap中获取analysisId
                            RaDeviateReason reason = reasonMap.get(reasonId);
                            if (reason != null && reason.getLinkedId() != null) {
                                consequenceEntity.setAnalysisId(reason.getLinkedId());
                            } else {
                                continue; // 没有原因ID，跳过
                            }
                        } else {
                            continue; // 没有原因ID，跳过
                        }

                        if (influenceId != null) {
                            consequenceEntity.setEffectId(influenceId.toString());
                        } else {
                            consequenceEntity.setEffectId("0"); // 默认值
                        }

                        // 设置来源后果节点ID
                        consequenceEntity.setFromConsequenceId(detail.getId() + "");

                        // 设置序号 - 从映射中获取序列号
                        Integer serialNum = detailIdToSerialNum.get(detail.getId());
                        consequenceEntity.setSerialNum(serialNum != null ? serialNum : 0);

                        // 设置后果类型
                        consequenceEntity.setConsequenceType(consequence.getEffectType() != null ? consequence.getEffectType().intValue() : 0);

                        // 设置描述信息
                        consequenceEntity.setConsequenceDesc(consequence.getEffectDesc());
                        consequenceEntity.setSeverityId(consequence.getSeverityGradeId() != null ? consequence.getSeverityGradeId() : 1L);

                        // 设置修正值
                        consequenceEntity.setCorrectedValue(!StringUtils.isEmpty(consequence.getCorrectedVal()) ? Integer.valueOf(consequence.getCorrectedVal()) : 0);

                        // 解析风险相关JSON数据
                        // 1. 解析初始风险数据
                        String originRiskJson = detail.getOriginRisk();
                        if (originRiskJson != null && !originRiskJson.isEmpty()) {
                            consequenceEntity.setInitialSeverityId(JsonUtils.getLongValue(originRiskJson, "$.severityId"));
                            consequenceEntity.setInitialLikelihoodId(JsonUtils.getLongValue(originRiskJson, "$.probabilityId"));
                            String originRiskGrade = JsonUtils.getStringValue(originRiskJson, "$.originRiskGrade");
                            consequenceEntity.setInitialLevelId(convertRiskGradeToId(riskGradeMap, originRiskGrade, consequence.getTenantId()));
                        }

                        // 2. 解析残余风险数据
                        String remnantRiskJson = detail.getRemnantRisk();
                        if (remnantRiskJson != null && !remnantRiskJson.isEmpty()) {
                            consequenceEntity.setResidualSeverityId(JsonUtils.getLongValue(remnantRiskJson, "$.severityId"));
                            consequenceEntity.setResidualLikelihoodId(JsonUtils.getLongValue(remnantRiskJson, "$.probabilityId"));
                            String remnantRiskGrade = JsonUtils.getStringValue(remnantRiskJson, "$.remnantRiskGrade");
                            consequenceEntity.setResidualLevelId(convertRiskGradeToId(riskGradeMap, remnantRiskGrade, consequence.getTenantId()));
                        }

                        // 3. 解析建议后风险数据
                        String afterAdviseJson = detail.getAfterAdvise();
                        if (afterAdviseJson != null && !afterAdviseJson.isEmpty()) {
                            consequenceEntity.setSuggestedSeverityId(JsonUtils.getLongValue(afterAdviseJson, "$.severityId"));
                            consequenceEntity.setSuggestedLikelihoodId(JsonUtils.getLongValue(afterAdviseJson, "$.probabilityId"));
                            String suggestedRiskGrade = JsonUtils.getStringValue(afterAdviseJson, "$.riskGrade");
                            consequenceEntity.setSuggestedLevelId(convertRiskGradeToId(riskGradeMap, suggestedRiskGrade, consequence.getTenantId()));
                        }

                        // 设置时间和创建人信息
                        consequenceEntity.setNodeRemark(detail.getRemark());
                        consequenceEntity.setCreateTime(CommonUtils.formatDateTime(consequence.getCreateTime()));
                        consequenceEntity.setUpdateTime(CommonUtils.formatDateTime(consequence.getCreateTime()));
                        consequenceEntity.setCreateBy(1L);
                        consequenceEntity.setUpdateBy(1L);
                        consequenceEntity.setIsDel(false);

                        consequenceEntityList.add(consequenceEntity);
                        newEntityManager.persist(consequenceEntity);

                        processedConsequenceIds.add(consequence.getId());
                    }
                }
            }
        }

        return consequenceEntityList;
    }

    @Override
    public List<RaConsequence> getAllConsequences(EntityManager oldEntityManager) {
        CriteriaBuilder oldCriteriaBuilder = oldEntityManager.getCriteriaBuilder();
        CriteriaQuery<RaConsequence> consequenceQuery = oldCriteriaBuilder.createQuery(RaConsequence.class);
        Root<RaConsequence> consequenceRoot = consequenceQuery.from(RaConsequence.class);
        consequenceQuery.select(consequenceRoot);
        consequenceQuery.where(oldCriteriaBuilder.equal(consequenceRoot.get("isDel"), (byte) 0));
        return oldEntityManager.createQuery(consequenceQuery).getResultList();
    }

    @Override
    public Map<Long, RaConsequence> buildConsequenceMap(List<RaConsequence> consequenceList) {
        return consequenceList.stream()
                .collect(java.util.stream.Collectors.toMap(RaConsequence::getId, consequence -> consequence, (a, b) -> a));
    }

    @Override
    public Map<Long, Set<Long>> buildSourceIdToConsequenceIdsMap(List<RaFaultChainsMeasure> measureList) {
        Map<Long, Set<Long>> sourceIdToConsequenceIds = new HashMap<>();

        // 处理措施关系，获取后果节点
        for (RaFaultChainsMeasure measure : measureList) {
            Long sourceId = measure.getSourceId();
            Byte sourceType = measure.getSourceType();

            if (sourceType != null && sourceType == 2) {
                // 后果节点
                sourceIdToConsequenceIds.computeIfAbsent(sourceId, k -> new HashSet<>()).add(sourceId);
            }
        }

        return sourceIdToConsequenceIds;
    }

    /**
     * 获取风险等级数据，并构建映射
     *
     * @param oldEntityManager 旧数据库实体管理器
     * @return 租户ID和风险等级到风险等级实体的映射
     */
    private Map<String, RaRiskGrade> getRiskGradeMap(EntityManager oldEntityManager) {
        CriteriaBuilder cb = oldEntityManager.getCriteriaBuilder();
        CriteriaQuery<RaRiskGrade> cq = cb.createQuery(RaRiskGrade.class);
        Root<RaRiskGrade> root = cq.from(RaRiskGrade.class);
        cq.where(cb.equal(root.get("isDel"), (byte) 0));
        List<RaRiskGrade> riskGradeList = oldEntityManager.createQuery(cq).getResultList();

        Map<String, RaRiskGrade> riskGradeMap = new HashMap<>();
        for (RaRiskGrade riskGrade : riskGradeList) {
            // 使用租户ID和风险等级作为键
            String key = (riskGrade.getTenantId() != null ? riskGrade.getTenantId() : 1) + "_" + riskGrade.getRiskLevel();
            riskGradeMap.put(key, riskGrade);
        }

        return riskGradeMap;
    }

    /**
     * 根据风险等级字母和租户ID查找对应的风险等级ID
     *
     * @param riskGradeMap 风险等级映射
     * @param riskGrade    风险等级字母
     * @param tenantId     租户ID
     * @return 风险等级ID
     */
    private Long convertRiskGradeToId(Map<String, RaRiskGrade> riskGradeMap, String riskGrade, Integer tenantId) {
        if (riskGrade == null || riskGrade.isEmpty()) {
            return null;
        }

        // 标准化租户ID，如果为空则使用默认值1
        Integer normalizedTenantId = tenantId != null ? tenantId : 1;

        // 构造键
        String key = normalizedTenantId + "_" + riskGrade;

        // 从映射中获取风险等级实体
        RaRiskGrade gradeEntity = riskGradeMap.get(key);

        // 如果找到了实体，返回其ID
        if (gradeEntity != null) {
            return gradeEntity.getId();
        }

        // 如果没有找到，尝试使用默认租户ID (1) 查询
        if (!normalizedTenantId.equals(1)) {
            key = "1_" + riskGrade;
            gradeEntity = riskGradeMap.get(key);
            if (gradeEntity != null) {
                return gradeEntity.getId();
            }
        }

        // 如果仍然找不到，返回默认ID
        return 1L;
    }

    @Override
    public int migrateConsequenceChemicalData(
            EntityManager oldEntityManager,
            EntityManager newEntityManager,
            List<RaConsequence> consequenceList) {

        long chemicalId = 1L; // 用于生成化学品关联记录的ID
        int rowCount = 0; // 记录处理的行数

        // 遍历所有后果节点
        for (RaConsequence consequence : consequenceList) {
            // 解析物料ID列表，格式为JSON数组: [{"id":2851,"linkedName":"铬硫酸"}]
            try {
                List<Map<String, Object>> chemicalsList = JsonUtils.parseJsonToList(consequence.getChemicalsIds());

                for (Map<String, Object> chemicalMap : chemicalsList) {
                    if (chemicalMap.containsKey("id")) {
                        Long linkedChemicalId = Long.valueOf(chemicalMap.get("id").toString());

                        // 创建后果节点-物料关联记录
                        RiskChainConsequenceChemical chemical = new RiskChainConsequenceChemical();

                        // 设置ID
                        chemical.setId(chemicalId++);

                        // 设置后果节点ID
                        chemical.setConsequenceId(consequence.getId().toString());

                        // 设置化学品ID
                        chemical.setChemicalId(linkedChemicalId);

                        // 持久化到数据库
                        newEntityManager.persist(chemical);
                        rowCount++; // 增加计数

                        log.info("迁移后果节点物料关联数据：后果节点ID={}, 物料ID={}", consequence.getId(), linkedChemicalId);
                    }
                }
            } catch (Exception e) {
                log.error("解析物料JSON数据失败: {}", consequenceList.size(), e);
            }
        }

        return rowCount; // 返回处理的行数
    }
}
